package main

import (
	"context"
	"fmt"
	common "git.mashibing.com/msb_47094/shopping-comm"
	"github.com/asim/go-micro/plugins/registry/consul/v4"
	"github.com/gin-gonic/gin"
	"github.com/plutov/paypal/v4"
	"github.com/smartwalle/alipay/v3"
	"go-micro.dev/v4"
	"go-micro.dev/v4/registry"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"payment/proto"
	"strings"
)

// 将公钥提供给支付宝（通过支付宝后台上传）对我们请求的数据进行签名验证，我们的代码中将使用私钥对请求数据签名。
// 目前新创建的支付宝应用只支持证书方式认证，已经弃用之前的公钥和私钥的方式
// 私钥:用于加密请求参数；
// 公钥：用于解密通过 私钥加密后的 请求参数。
var (
	// appId
	APPID = "2021000116681444"
	// 应用公钥
	AliAppPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1o6GRM72PKbU299+VmOd1527hKp+//fpEPkz7yBHBCoaAAASuIaaQyuHHtJAcjVlb4XNjLoRyIXQ71rPQaucs/5qjmvyPAlfBNJhVaUAV5ZX7WtXHMAEdTBzVODP5axjY5BSzSmpvm9fNPDuaU3ayyqENP5yoHFs2zTSpnwRoh9Ct+urqfrAJRBx435OwVJ6Abv6blKcXMSRLlgq9hM5fbzFHv7OQ8QXvrsB9NA6s2PELI5hbLFuW0T8WyX4AaFIo2SHnHGludrDwKCxO3HolwjZoQKNcsZhDOG0A3kcVUowpnP3SqkbsfVId943KxvXTIouAoYYbfD6/BKcVlC/QIDAQAB"
	//支付宝公钥
	AliPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhA9A6B+gV6pzSv9KKUFcqMZKrFIYOamHIeviQy6KgFuWekGG7KA6agJyGaYrogTpp97NyopgORAK+D5J7bRdcJ1smkpHlyXF0P8D9H/+wZn++1TSQYWWoPJbQXX+l0Ma42O6ISckwXHeZr0tLWUaAoTnTkSAqR0e5LtAFusND6EY/pFFJONxM2Fouwb9WiNCw6J1zQDpO1Y0bxVgQy9v19N/Qw04MtPakua2BqyZctbLggA8WhusCzbTMRZCcOXdYFajPqSvVz5278K6RGKjVeDVBUuaUcA394v1I9tHIa41o8P7j0DhFfDS5Lo8npjhkxcF2wHqfzf5NH041jwAQQIDAQAB"
	//私钥
	PrivateKey    = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCnWjoZEzvY8ptTb335WY53XnbuEqn7/9+kQ+TPvIEcEKhoAABK4hppDK4ce0kByNWVvhc2MuhHIhdDvWs9Bq5yz/mqOa/I8CV8E0mFVpQBXllfta1ccwAR1MHNU4M/lrGNjkFLNKam+b1808O5pTdrLKoQ0/nKgcWzbNNKmfBGiH0K366up+sAlEHHjfk7BUnoBu/puUpxcxJEuWCr2Ezl9vMUe/s5DxBe+uwH00DqzY8QsjmFssW5bRPxbJfgBoUijZIeccaW52sPAoLE7ceiXCNmhAo1yxmEM4bQDeRxVSjCmc/dKqRux9Uh33jcrG9dMii4Chhht8Pr8EpxWUL9AgMBAAECggEAYsQ3QZE+Yt1bmjRUrpKSKBTSL9NICveJ75I6OffQYtXZ7fcCNS+X0qOvJhQElE8I7qUPYedNep2+CTaDUbLdxdjEShhdjENefAmN/GmKU/xw1rGMLOGaCuv7rMg6z46KHzbzhgT+zdDaag84lhnRySjE/cV8yG0qVqhFUuPjEFyMrY8lb/68P+E3P4Vm+hvdaOe10ayLmYm7YBh4Z7eSdhSxENBs+7dIG37Z2xC6FQRPm5qLrFdP03tianX71ZU/J7yky4HceqW4lIW8g4CSbWlCKewaucvnZ7q449/P/PSIbPr4KxQS8bGooQF6LGYEkRISWpYIQWBSjXvUU7PDaQKBgQDV3Hgwp93FdLU414ArdXzbklzVC3SEKdIXEBmt9s+Ec13I1xPDjM1HFezow4S/aaqi5soYyR6koVvsaXeHk+cNlphgZj6lz+p0BQvCvTrjkRFwSDdlBNuxgaiwZbjjUHZPwO42d3k2kiUwyRNcGIyDyPzo4b19D06VX2JIKdpp+wKBgQDIU8ZfQUj11Zgqx/dqd5XASGtoSQNwZPROJyLFwTMg6okgdevdoWaFgRUttPDRBhdcrtmVq7voJ35xoriKNFCSvkZc8GAVKiYgIGLXNscDKZx1EP5yc9VVbUnnTW4QXBQRB+VcLGmuh1DOPTkP+sEsTZhPM5TTMCX9HxrDtW6tZwKBgQCAlkBaGQTaTbMNC14QQ2Mgbp+MpYeYU8DzhwW5uNXLcMZqFQ/YG1fuLvu0dKLjqHgl3JiVUJAxMqgfvMZW6ZIadHsIM1Hlxt7UhZgtrjOzUq1mkrVj8wjZcPlpnrANVXrdt0ZDz5A9RKBB9hTC4ivSrU2MBPc3M7XvUFu6wheGcwKBgQCCMCeIOiZPVWuZyfDZ6TOSDb53vJOWlJVMwRRRDljK+ID7bodFtqGo+5Wm6aNjRCEko6FWKpBotFnxQb3KW2tNooiZ18Gpn4W9dS6nDLtTK9S5I70o5mxrIyZXQrPXv+9ujgIZ3+cifGAgWBtgbibiQt9MAYqjoPPfRzqem6d82wKBgQCjcqFOK7Ff0bSz6S2PzFLWyHBlrEKXI+9+9N5nS8aFB8uJduu0PqK4CXs6FqbY+6xuZ9Qdhe9j2NXoqZoJyQlb8/aL1etT+/JP0Md9Wi0v9SVnnz6Ci1RmJEjO02Q/xrpphEbK87h7YpNUI4flHR4ZCr9EmXqdXRTuXImUImc3uw=="
	ApliClient, _ = alipay.New(APPID, PrivateKey, false)

	FindOrderClient    = proto.NewFindOrderService("", nil)
	UpdateTraderClient = proto.NewUpdateTradeOrderService("", nil)
	//PayPal国际支付
	PayPalClientID  = "AX5c8C-Z9P5vXgs22Q3MWKaEKvVa5-vtU3jtNrQe8W2s-x8eXYn_2aA-e4paaHo6I0Z9eba0Ur2LTdZI"
	PayPalPublicKey = ""
	PayPalSecretID  = "EB_svAAyczD2OoCMh2HMA4ApBysCbHli8gOpFUfKLOaI5zkoePeNd54OI1PT5yDtAqNsWgho7IYNdqFR"
	//真实环境  paypal.APIBaseLive
	PaypalClient, _ = paypal.NewClient(PayPalClientID, PayPalSecretID, paypal.APIBaseSandBox)
)

// 初始化的init
func init() {
	//PayPal国际支付
	//PaypalClient, _ = paypal.NewClient(PayPalClientID, PayPalSecretID, paypal.APIBaseSandBox)
	PaypalClient.SetLog(os.Stdout) // Set log to terminal stdout
	accessToken, err := PaypalClient.GetAccessToken(context.Background())
	fmt.Println("PayPal国际支付 :\n", accessToken, "     \n ", err)
	//支付宝支付
	ApliClient.LoadAppPublicCert(AliAppPublicKey)
	ApliClient.LoadAliPayPublicCert(AliPublicKey)
	//证书的方式 ApliClient.LoadAliPayRootCert()
	//注册中心
	consulReg := consul.NewRegistry(func(options *registry.Options) {
		options.Addrs = []string{common.ConsulReistStr}
	})
	rpcServer := micro.NewService(
		micro.Name("shop-payment"),
		micro.Registry(consulReg),
	)
	FindOrderClient = proto.NewFindOrderService("trade-order", rpcServer.Client())
	UpdateTraderClient = proto.NewUpdateTradeOrderService("trade-order", rpcServer.Client())

}
func TradeWapPayPal(c *gin.Context) {
	//order, err := PaypalClient.CreateOrder(paypal.OrderIntentCapture, []paypal.PurchaseUnitRequest{paypal.PurchaseUnitRequest{ReferenceID: "ref-id", Amount: paypal.Amount{Total: "7.00", Currency: "USD"}}})
}

// 手机端的支付  弹出选择APP 还是 H5
func TradeWapAliPay(c *gin.Context) {
	fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TradeAppAliPay ")
	var pay = alipay.TradeWapPay{}
	pay.TotalAmount = c.Query("payAmount")
	pay.OutTradeNo = c.Query("orderNo")
	//支付之后  支付宝回调的API
	//pay.ReturnURL = "http://127.0.0.1:8086/return"
	pay.NotifyURL = "http://j8utmw.natappfree.cc/return"
	pay.Body = "APP订单"
	pay.Subject = "商品标题"
	res, err := ApliClient.TradeWapPay(pay)
	if err != nil {
		fmt.Println("支付失败 :", err)
	}
	payURL := res.String()
	payURL = strings.Replace(payURL, "&", "^&", -1)
	exec.Command("cmd", "/c", "start", payURL).Start()
}

// 网站页面扫码支付
func TradePageAlipay(c *gin.Context) {
	fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> TradePageAlipay ")
	var p = alipay.TradePagePay{}
	p.NotifyURL = "http://j8utmw.natappfree.cc/return" //支付异步
	//p.ReturnURL = "http://127.0.0.1:8086/return" //同步
	p.Subject = "商品支付"
	p.OutTradeNo = c.Query("orderNo")
	p.TotalAmount = c.Query("payAmount")
	p.ProductCode = "FAST_INSTANT_TRADE_PAY["
	res, err := ApliClient.TradePagePay(p)
	if err != nil {
		fmt.Println("支付失败 :", err)
	}
	payURL := res.String()
	payURL = strings.Replace(payURL, "&", "^&", -1)
	exec.Command("cmd", "/c", "start", payURL).Start()
}

// 回调函数
/*
gmt_create=2022-11-17+13%3A39%3A42&
charset=utf-8&
gmt_payment=2022-11-17+13%3A39%3A48&
notify_time=2022-11-17+13%3A39%3A49&
subject=%E4%BF%AE%E6%AD%A3%E4%BA%86%E4%B8%AD%E6%96%87%E7%9A%84+Bug&
sign=Q%2FqJv73maQ45zEdJfYfce9%2FeCDYx03otzJL67wetT1q%2Ft1vrVrpf8EHDpDQxKzcchDqOJ%2B1v3lDyhHwd4KUHd3z9APw%2BGzonHYgccuLNwEwaYQ8Pv7PjzFMOvS2HiHptUdYMWFXKHnYi3AE%2FuBtxGASljBuMms9jnABf1xFM4BVVhdmtSdMtlhbJ0eDNNs0pAs1tdCXdX%2FV6j%2BWi6GSU7VYMRzhzhlWYm%2FTSZao4QNqjkoY6j1G4MWx%2Fvmyk3SgItDSEpECxzO2Vt0F0slbTUJwqllkQ%2Fk323VvXFBHxHOxltpnrZfegYK%2B0mE4jcpQ9jRCnXRCDMHKI9adl6kJX9A%3D%3D&
buyer_id=2088622955228317&
invoice_amount=10.00&
version=1.0&
notify_id=2022111700222133949028310528415537&
fund_bill_list=%5B%7B%22amount%22%3A%2210.00%22%2C%22fundChannel%22%3A%22ALIPAYACCOUNT%22%7D%5D&
notify_type=trade_status_sync&
out_trade_no=2022-11-17+13%3A39%3A33.8566275+%2B0800+CST+m%3D%2B3.273247501&
total_amount=10.00&
trade_status=TRADE_SUCCESS&
trade_no=2022111722001428310502276237&
auth_app_id=2021000116681444&
receipt_amount=10.00&
point_amount=0.00&
app_id=2021000116681444&
buyer_pay_amount=10.00&
sign_type=RSA2&
seller_id=2088621954959062

*/
func AliPayNotify(c *gin.Context) {
	fmt.Println(" >>>>>>>>>>>>>>>>>  AliPayNotify >>>>>>>>>>>>>>>>>")
	//获取请求报文的长度
	//conLen := c.Request.ContentLength
	////新建一个字节切片 长度
	//body := make([]byte, conLen)
	//n, _ := c.Request.Body.Read(body)
	//改进读取的方法
	data, _ := ioutil.ReadAll(c.Request.Body)
	vals := string(data[0:len(data)])
	fmt.Println(vals)
	//验证是否支付成功
	if strings.Contains(vals, "TRADE_SUCCESS") {
		kv := strings.Split(vals, "&")
		var no string
		for k, v := range kv {
			fmt.Println(k, ":", v)
			//out_trade_no=xxxx
			if strings.HasPrefix(v, "out_trade_no") {
				index := strings.Index(v, "=")
				no = v[index+1 : len(v)]
			}
		}
		fmt.Println("订单:", no, "成功支付")
		//远程调用 服务
		//查询订单详情
		req := &proto.FindOrderReq{}
		//req.Id =
		req.OrderNo = no

		obj, err := FindOrderClient.FindOrder(context.TODO(), req)
		if err != nil {
			log.Println("findOrder err :", err)
			//common.RespFail(c.Writer, resp, "查询失败")
		}
		fmt.Println("findOrder:", obj)
		//c.JSON(http.StatusOK, gin.H{"findOrder": "SUCCESS", "Message": obj})
		//修改订单
		reqUpdate := &proto.AddTradeOrderReq{}
		tradeOrder := &proto.TradeOrder{}
		tradeOrder.ID = obj.TradeOrder.ID
		reqUpdate.TradeOrder = tradeOrder
		//订单状态（1：待支付，2：已关闭，3：已支付，4：已发货，5：已收货，6：已完成，7：已追评）
		reqUpdate.TradeOrder.OrderStatus = 3
		_, err = UpdateTraderClient.UpdateTradeOrder(context.TODO(), reqUpdate)
		if err != nil {
			log.Println("/UpdateTradeOrder err ", err)
			return
		}
		c.JSON(http.StatusOK, gin.H{"reslut": "SUCCESS", "Message": "修改订单支付成功!"})
	}

}

// 生成收款订单
func CreateOrderPayer(c *gin.Context) {

	purchaseUnits := make([]paypal.PurchaseUnitRequest, 1)
	purchaseUnits[0] = paypal.PurchaseUnitRequest{
		Amount: &paypal.PurchaseUnitAmount{
			Currency: "USD",             //收款类型
			Value:    c.Query("amount"), //收款数量
		},
		InvoiceID:   c.Query("orderNo"),
		ReferenceID: "123",
		Description: "商品支付",
	}
	payer := &paypal.CreateOrderPayer{
		Name: &paypal.CreateOrderPayerName{
			//GivenName: user_idStr,
			//Surname:   user_idStr,
		},
	}
	appContext := &paypal.ApplicationContext{
		ReturnURL: "http://j8utmw.natappfree.cc/payPalBack?orderNo=" + c.Query("orderNo"), //回调链接
	}
	//CreateOrder(ctx context.Context, intent string, purchaseUnits []PurchaseUnitRequest, payer *CreateOrderPayer, appContext *ApplicationContext)
	orderResponse, err := PaypalClient.CreateOrder(context.Background(), "CAPTURE", purchaseUnits, payer, appContext)
	if err != nil {
		log.Println("create order errors:", err)
		c.JSON(http.StatusNotExtended, gin.H{"reslut": err, "Message": "构建订单失败!", "CODE": http.StatusNotExtended})
		return
	}
	//c.Header("ID", orderResponse.ID)
	payURL := (*orderResponse).Links[1].Href
	payURL = strings.Replace(payURL, "&", "^&", -1)
	common.SetUserToken()
	//https://www.sandbox.paypal.com/checkoutnow?token=85V82337B3775564V
	exec.Command("cmd", "/c", "start", payURL).Start()
	//(*order).Links[1].Href就是支付的链接

}

// 回调(可以利用上面的回调链接实现)
// https://www.sandbox.paypal.com/webapps/hermes?
// flow=1-P&ulReturn=true&
// token=85V82337B3775564V&
// rcache=2&
// useraction=CONTINUE&
// cookieBannerVariant=1&
// targetService4174=xorouternodeweb&country.x=C2&
// locale.x=zh_XC
func PaypalCallback(c *gin.Context) {
	//c, err := paypal.NewClient(clientID, secretID, paypal.APIBaseSandBox)
	//if err != nil {
	//	return err
	//}
	//_, err = c.GetAccessToken()
	//if err != nil {
	//	return err
	//}
	//“status”:“COMPLETED 或者 PENDING” 说明支付成功了
	ctor := paypal.CaptureOrderRequest{}
	//CaptureOrder(ctx context.Context, orderID string, captureOrderRequest CaptureOrderRequest)
	order, err := PaypalClient.CaptureOrder(context.Background(), c.Query("ID"), ctor)
	o, _ := PaypalClient.GetOrder(context.Background(), c.Query("ID"))
	log.Println(o, "\n", order)
	if err != nil {
		log.Println("/UpdateTradeOrder err ", err)
		//return
	}

	//查看回调完成后订单状态是否支付完成。
	if (*order).Status != "COMPLETED" {
		log.Println("/UpdateTradeOrder err ", err)
		c.JSON(http.StatusNotExtended, gin.H{"reslut": err, "Message": "订单回调失败!", "CODE": http.StatusNotExtended})
		return
	}
	c.JSON(http.StatusOK, gin.H{"reslut": "SUCCESS", "Message": "修改订单支付成功!"})
}
func main() {
	r := gin.Default()
	r.SetTrustedProxies([]string{common.QSIp})
	r.GET("/appPay", TradeWapAliPay)
	r.GET("/pagePay", TradePageAlipay)
	r.POST("/return", AliPayNotify)
	//payPal
	r.GET("/payPal", CreateOrderPayer)
	r.GET("/payPalBack", PaypalCallback)
	r.Run(":8086")
}
